package lesson05.blocking_queue;

/**
 * 实现一个阻塞队列
 *
 * @author wileda
 * @date 2023/01/12  16:25
 */
public class MyBlockingQueue {
    //需要一个数组来保存数据
    private Integer[] elementData = new Integer[100];
    //队尾与队首下标
    private volatile int head = 0;
    private volatile int tail = 0;
    //有效个数元素
    private volatile int size = 0;

    public void put(Integer value) throws InterruptedException {
        synchronized(this){
            //判断队列是否已满，如果满了则阻塞
            while(size >= elementData.length) {
                this.wait();
            }
            //从队尾入队
            elementData[tail] = value;
            //tail往后走
            tail++;
            //循环处理
            if(tail >= elementData.length){
                tail = 0;
            }
            //有效元素加一
            size++;
            //唤醒其他线程
            this.notifyAll();
        }
    }

    public int take() throws InterruptedException {
        synchronized(this){
            //先判断队列是否为空
            while(size == 0){
                //队列为空，出队阻塞
                this.wait();
            }
            //取出队头元素
            Integer value = elementData[head];
            //head往后走一步
            head++;
            //循环判断
            if(head >= elementData.length){
                head = 0;
            }
            //有效元素减一
            size--;
            //出队时唤醒其他线程
            this.notifyAll();
            //返回出队的值
            return value;
        }
    }
}
